package org.tinygroup.flow.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.tinygroup.commons.tools.StringUtil;
import org.tinygroup.flow.ComponentInterface;
import org.tinygroup.flow.FlowExecutor;
import org.tinygroup.flow.config.ComponentDefine;
import org.tinygroup.flow.config.ComponentDefines;
import org.tinygroup.flow.config.Flow;
import org.tinygroup.flow.containers.ComponentContainers;
import org.tinygroup.flow.exception.FlowRuntimeException;
import org.tinygroup.flow.exception.errorcode.FlowExceptionErrorCode;
import org.tinygroup.logger.LogLevel;
import org.tinygroup.logger.Logger;
import org.tinygroup.logger.LoggerFactory;

public abstract class AbstractFlowExecutorImpl implements FlowExecutor{
	private static final Logger LOGGER = LoggerFactory
            .getLogger(AbstractFlowExecutorImpl.class);
	 	private boolean change;
	    // 组件容器
	    private ComponentContainers containers = new ComponentContainers();
	    private Map<String, Flow> flowIdMap = new HashMap<String, Flow>();// 包含了name和id两个，所以通过名字和id都可以访问
	    
	    public void addComponents(ComponentDefines components) {
	        containers.addComponents(components);
	    }

	    public void removeComponents(ComponentDefines components) {
	        containers.removeComponents(components);
	    }
	    
	    /**
	     * 根据流程组件信息实例化组件
	     *
	     * @param componentName 流程组件名
	     * @return
	     */
	    public ComponentInterface getComponentInstance(String componentName) {
	        ComponentInterface componentInstance = null;
	        if (!StringUtil.isBlank(componentName)) {
	            componentInstance = containers.getComponentInstance(componentName);
	            return componentInstance;
	        }
	        throw new FlowRuntimeException(FlowExceptionErrorCode.FLOW_COMPONENT_NOT_EXIST, componentName);
	    }
	    public void addComponent(ComponentDefine component) {
	        containers.addComponent(component);
	    }

	    public void removeComponent(ComponentDefine component) {
	        containers.removeComponent(component);
	    }

	    public ComponentDefine getComponentDefine(String componentName) {
	        return containers.getComponentDefine(componentName);
	    }

	    public boolean isChange() {
	        return change;
	    }

	    public void setChange(boolean change) {
	        this.change = change;
	    }

	    public List<ComponentDefine> getComponentDefines() {
	        return containers.getComponentDefines();
	    }
	    
	    public void assemble() {
	        for (Flow flow : flowIdMap.values()) {
	            flow.validate();
	            flow.assemble();
	        }
	    }

	    public void addFlow(Flow flow) {
	        if (flow.getId() != null && flowIdMap.get(flow.getId()) != null) {
	            LOGGER.logMessage(LogLevel.ERROR, "flow:[id:{0}]已经存在！",
	                    flow.getId());
	        }
	        if (flow.getName() != null && flowIdMap.get(flow.getName()) != null) {
	            LOGGER.logMessage(LogLevel.ERROR, "flow:[name:{0}]已经存在！",
	                    flow.getName());
	        }
	        if (flow.getId() != null) {
	            LOGGER.logMessage(LogLevel.INFO, "添加flow:[id:{0}]", flow.getId());
	            flowIdMap.put(flow.getId(), flow);
	        }
	        if (flow.getName() != null) {
	            LOGGER.logMessage(LogLevel.INFO, "添加flow:[Name:{0}]",
	                    flow.getName());
	            flowIdMap.put(flow.getName(), flow);
	        }
	        flow.setFlowExecutor(this);
	        setChange(true);
	    }

	    public void removeFlow(Flow flow) {
	        LOGGER.logMessage(LogLevel.INFO, "移除flow:[id:{0}]", flow.getId());
	        flowIdMap.remove(flow.getId());
	        LOGGER.logMessage(LogLevel.INFO, "移除flow:[name:{0}]", flow.getName());
	        flowIdMap.remove(flow.getName());
	        setChange(true);
	    }

	    public void removeFlow(String flowId) {
	        Flow flow = getFlow(flowId);
	        removeFlow(flow);
	    }

	    public Flow getFlow(String flowId) {
	        return flowIdMap.get(flowId);
	    }
	    public Map<String, Flow> getFlowIdMap() {
	        return flowIdMap;
	    }

}


